/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_variables,
    unused_unsafe,
    clippy::never_loop,
    clippy::double_parens
)]

use crate::common::*;

extern "C" {
    fn umask(__mask: __mode_t) -> __mode_t;
    fn snprintf(
        _: *mut libc::c_char,
        _: libc::c_ulong,
        _: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    fn asprintf(__ptr: *mut *mut libc::c_char, __fmt: *const libc::c_char, _: ...) -> libc::c_int;
    fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
    fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void;
    fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int;
    fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
    fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char;
    fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn close(__fd: libc::c_int) -> libc::c_int;
    fn __errno_location() -> *mut libc::c_int;
    fn parse_timeout(timestr: *const libc::c_char) -> libc::c_int;
    static mut sudo_defs_table: [sudo_defs_types; 120];
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warn_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warn_gettext_v1(
        domainname: *const libc::c_char,
        msgid: *const libc::c_char,
    ) -> *mut libc::c_char;
    fn sudo_fatal_callback_deregister_v1(func: sudo_fatal_callback_t) -> libc::c_int;
    fn sudo_parse_gids_v1(
        gidstr: *const libc::c_char,
        basegid: *const gid_t,
        gidsp: *mut *mut gid_t,
    ) -> libc::c_int;
    fn sudo_new_key_val_v1(
        key: *const libc::c_char,
        value: *const libc::c_char,
    ) -> *mut libc::c_char;
    fn sudo_strtobool_v1(str: *const libc::c_char) -> libc::c_int;
    fn sudo_strtonum(
        _: *const libc::c_char,
        _: libc::c_longlong,
        _: libc::c_longlong,
        _: *mut *const libc::c_char,
    ) -> libc::c_longlong;
    fn sudo_strtoid_v2(str: *const libc::c_char, errstr: *mut *const libc::c_char) -> id_t;
    fn sudo_strtomode_v1(cp: *const libc::c_char, errstr: *mut *const libc::c_char) -> libc::c_int;
    fn sudo_debug_enter_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
    );
    fn sudo_debug_exit_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
    );
    fn sudo_debug_exit_int_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
        ret: libc::c_int,
    );
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn timestamp_remove(unlinkit: bool) -> libc::c_int;
    fn sudo_auth_needs_end_session() -> bool;
    fn sudo_auth_begin_session(
        pw: *mut passwd,
        user_env: *mut *mut *mut libc::c_char,
    ) -> libc::c_int;
    fn sudo_auth_end_session(pw: *mut passwd) -> libc::c_int;
    fn dcgettext(
        __domainname: *const libc::c_char,
        __msgid: *const libc::c_char,
        __category: libc::c_int,
    ) -> *mut libc::c_char;
    fn sudo_gidlist_delref(_: *mut gid_list);
    static mut sudoers_file: *const libc::c_char;
    static mut sudoers_mode: mode_t;
    static mut sudoers_uid: uid_t;
    static mut sudoers_gid: gid_t;
    fn dump_defaults();
    fn dump_auth_methods();
    fn sudo_gr_delref(_: *mut group);
    fn sudo_get_gidlist(pw: *const passwd, type_0: libc::c_uint) -> *mut gid_list;
    fn sudo_getpwnam(_: *const libc::c_char) -> *mut passwd;
    fn sudoers_hook_getenv(
        name: *const libc::c_char,
        value: *mut *mut libc::c_char,
        closure: *mut libc::c_void,
    ) -> libc::c_int;
    fn sudo_pw_delref(_: *mut passwd);
    fn sudoers_hook_setenv(
        name: *const libc::c_char,
        value: *const libc::c_char,
        overwrite: libc::c_int,
        closure: *mut libc::c_void,
    ) -> libc::c_int;
    fn sudoers_hook_unsetenv(name: *const libc::c_char, closure: *mut libc::c_void) -> libc::c_int;
    fn sudoers_policy_init(info: *mut libc::c_void, envp: *const *mut libc::c_char) -> libc::c_int;
    fn sudoers_hook_putenv(string: *mut libc::c_char, closure: *mut libc::c_void) -> libc::c_int;
    static mut path_plugin_dir: *const libc::c_char;
    fn sudoers_debug_deregister();
    fn sudoers_debug_register(
        plugin_path: *const libc::c_char,
        debug_files: *mut sudo_conf_debug_file_list,
    ) -> bool;
    fn sudoers_debug_parse_flags(
        debug_files: *mut sudo_conf_debug_file_list,
        entry: *const libc::c_char,
    ) -> bool;
    fn sudoers_gc_add(type_0: libc::c_uint, ptr: *mut libc::c_void) -> bool;
    static mut sudo_mode: libc::c_int;
    fn sudoers_policy_main(
        argc: libc::c_int,
        argv: *const *mut libc::c_char,
        pwflag: libc::c_int,
        env_add: *mut *mut libc::c_char,
        verbose: bool,
        closure: *mut libc::c_void,
    ) -> libc::c_int;
    fn sudoers_cleanup();
    static mut sudo_user: sudo_user;
    static mut list_pw: *mut passwd;
    static mut force_umask: bool;
    fn dump_interfaces(_: *const libc::c_char);
    fn set_interfaces(_: *const libc::c_char) -> bool;
}

pub type sudo_fatal_callback_t = Option<unsafe extern "C" fn() -> ()>;

// 多处定义，后期统一处理
pub const kernel: libc::c_uint = 9;
pub const tty: libc::c_uint = 8;
pub const ppid: libc::c_uint = 7;
pub const global: libc::c_uint = 6;
pub const digest_only: libc::c_uint = 5;
pub const all: libc::c_uint = 4;
pub const any: libc::c_uint = 3;
pub const always: libc::c_uint = 2;
pub const once: libc::c_uint = 1;
pub const never: libc::c_uint = 0;

// 多处定义，后期统一处理
#[derive(Copy, Clone)]
#[repr(C)]
pub struct list_member {
    pub entries: C2RustUnnamed,
    pub value: *mut libc::c_char,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2RustUnnamed {
    pub sle_next: *mut list_member,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct list_members {
    pub slh_first: *mut list_member,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct def_values {
    pub sval: *mut libc::c_char,
    pub nval: libc::c_uint,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union sudo_defs_val {
    pub flag: libc::c_int,
    pub ival: libc::c_int,
    pub uival: libc::c_uint,
    pub tuple: libc::c_uint,
    pub str_0: *mut libc::c_char,
    pub mode: mode_t,
    pub tspec: timespec,
    pub list: list_members,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_defs_types {
    pub name: *mut libc::c_char,
    pub type_0: libc::c_int,
    pub desc: *mut libc::c_char,
    pub values: *mut def_values,
    pub callback: Option<unsafe extern "C" fn(*const sudo_defs_val) -> bool>,
    pub sd_un: sudo_defs_val,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct gid_list {
    pub ngids: libc::c_int,
    pub gids: *mut gid_t,
}
pub type sudo_conv_t = Option<
    unsafe extern "C" fn(
        libc::c_int,
        *const sudo_conv_message,
        *mut sudo_conv_reply,
        *mut sudo_conv_callback,
    ) -> libc::c_int,
>;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_user {
    pub pw: *mut passwd,
    pub _runas_pw: *mut passwd,
    pub _runas_gr: *mut group,
    pub cmnd_stat: *mut stat,
    pub name: *mut libc::c_char,
    pub path: *mut libc::c_char,
    pub tty: *mut libc::c_char,
    pub ttypath: *mut libc::c_char,
    pub host: *mut libc::c_char,
    pub shost: *mut libc::c_char,
    pub runhost: *mut libc::c_char,
    pub srunhost: *mut libc::c_char,
    pub prompt: *mut libc::c_char,
    pub cmnd: *mut libc::c_char,
    pub cmnd_args: *mut libc::c_char,
    pub cmnd_base: *mut libc::c_char,
    pub cmnd_safe: *mut libc::c_char,
    pub class_name: *mut libc::c_char,
    pub krb5_ccname: *mut libc::c_char,
    pub gid_list: *mut gid_list,
    pub env_vars: *const *mut libc::c_char,
    pub role: *mut libc::c_char,
    pub type_0: *mut libc::c_char,
    pub cwd: *const libc::c_char,
    pub iolog_file: *mut libc::c_char,
    pub gids: *mut gid_t,
    pub execfd: libc::c_int,
    pub ngids: libc::c_int,
    pub closefrom: libc::c_int,
    pub lines: libc::c_int,
    pub cols: libc::c_int,
    pub flags: libc::c_int,
    pub max_groups: libc::c_int,
    pub timeout: libc::c_int,
    pub umask: mode_t,
    pub uid: uid_t,
    pub gid: uid_t,
    pub sid: pid_t,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudoers_policy_open_info {
    pub settings: *const *mut libc::c_char,
    pub user_info: *const *mut libc::c_char,
    pub plugin_args: *const *mut libc::c_char,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudoers_exec_args {
    pub argv: *mut *mut *mut libc::c_char,
    pub envp: *mut *mut *mut libc::c_char,
    pub info: *mut *mut *mut libc::c_char,
}

// #define MATCHES(s, v)	\
//     (strncmp((s), (v), sizeof(v) - 1) == 0)
macro_rules! MATCHES {
    ($s:expr, $v:expr, $len:expr) => {
        strncmp(
            $s,
            $v as *const u8 as *const libc::c_char,
            (::core::mem::size_of::<[libc::c_char; $len]>() as libc::c_ulong)
                .wrapping_sub(1 as libc::c_int as libc::c_ulong),
        ) == 0 as libc::c_int
    };
}

// #define CHECK(s, v) do {	\
//     if ((s)[sizeof(v) - 1] == '\0') { \
// 	sudo_warn(U_("invalid %.*s set by sudo front-end"), \
// 	    (int)(sizeof(v) - 2), v); \
// 	goto bad; \
//     } \
// } while (0)
#[macro_export]
macro_rules! CHECK {
    ($s:expr, $v:expr, $len:expr) => {
        if *($s).offset(
            (::core::mem::size_of::<[libc::c_char; $len]>() as libc::c_ulong)
                .wrapping_sub(1 as libc::c_ulong) as isize,
        ) as libc::c_int
            == '\0' as i32
        {
            sudo_warn!(
                b"invalid %.*s set by sudo front-end\0" as *const u8 as *const libc::c_char,
                (::core::mem::size_of::<[libc::c_char; $len]>() as libc::c_ulong)
                    .wrapping_sub(2 as libc::c_ulong) as libc::c_int,
                $v as *const u8 as *const libc::c_char,
            );
            // 	goto bad;
            debug_return_int!(MODE_ERROR);
        }
    };
}

// #define MODE_ERROR		0x00000200
pub const MODE_ERROR: libc::c_int = 0x00000200;

pub const RUNAS_USER_SPECIFIED: libc::c_int = 0x01;
pub const RUNAS_GROUP_SPECIFIED: libc::c_int = 0x02;

pub const GC_PTR: libc::c_uint = 2;
pub const GC_VECTOR: libc::c_uint = 1;
pub const GC_UNKNOWN: libc::c_uint = 0;
static mut sudo_version: libc::c_uint = 0;
static mut interfaces_string: *const libc::c_char = 0 as *const libc::c_char;
#[no_mangle]
pub static mut sudo_conv: sudo_conv_t = None;
#[no_mangle]
pub static mut sudo_printf: sudo_printf_t = None;

#[no_mangle]
pub static mut path_ldap_conf: *const libc::c_char = _PATH_LDAP_CONF!();

#[no_mangle]
pub static mut path_ldap_secret: *const libc::c_char = _PATH_LDAP_SECRET!();

fn parse_bool(
    mut line: *const libc::c_char,
    mut varlen: libc::c_int,
    mut flags: *mut libc::c_int,
    mut fval: libc::c_int,
) -> libc::c_int {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        match sudo_strtobool_v1(
            line.offset(varlen as isize)
                .offset(1 as libc::c_int as isize),
        ) {
            1 => {
                SET!(*flags, fval);
                debug_return_int!(true as libc::c_int);
            }
            0 => {
                CLR!(*flags, fval);
                debug_return_int!(false as libc::c_int);
            }
            _ => {
                sudo_warn!(
                    b"invalid %.*s set by sudo front-end\0" as *const u8 as *const libc::c_char,
                    varlen,
                    line
                );
                debug_return_int!(-1);
            }
        };
    } //unsafe
}

/*
 * Deserialize args, settings and user_info arrays.
 * Fills in struct sudo_user and other common sudoers state.
 */
#[no_mangle]
pub fn sudoers_policy_deserialize_info(
    mut v: *mut libc::c_void,
    mut runas_user: *mut *mut libc::c_char,
    mut runas_group: *mut *mut libc::c_char,
) -> libc::c_int {
    let edit_mask: libc::c_int = MODE_EDIT | MODE_IGNORE_TICKET | MODE_NONINTERACTIVE;
    let mut info: *mut sudoers_policy_open_info = v as *mut sudoers_policy_open_info;
    let mut p: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut errstr: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut groups: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut remhost: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut cur: *const *mut libc::c_char = std::ptr::null::<*mut libc::c_char>();
    let mut flags: libc::c_int = 0 as libc::c_int;

    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        /* Parse sudo.conf plugin args. */
        if !((*info).plugin_args).is_null() {
            cur = (*info).plugin_args;
            loop {
                if (*cur).is_null() {
                    break;
                }

                if MATCHES!(*cur, b"sudoers_file=\0", 14) {
                    CHECK!(*cur, b"sudoers_file=\0", 14);
                    sudoers_file = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));
                    cur = cur.offset(1);
                    continue;
                }
                if MATCHES!(*cur, b"sudoers_uid=\0", 13) {
                    p = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));

                    sudoers_uid = sudo_strtoid_v2(p, &mut errstr);
                    if !errstr.is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            *cur,
                            errstr
                        );
                        // goto bad;
                        debug_return_int!(MODE_ERROR);
                    }
                    cur = cur.offset(1);
                    continue;
                }

                if MATCHES!(*cur, b"sudoers_gid=\0", 13) {
                    p = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));
                    sudoers_gid = sudo_strtoid_v2(p, &mut errstr);
                    if !errstr.is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            *cur,
                            errstr
                        );
                        // goto bad;
                        debug_return_int!(MODE_ERROR);
                    }
                    cur = cur.offset(1);
                    continue;
                }

                if MATCHES!(*cur, b"sudoers_mode=\0", 14) {
                    p = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));
                    sudoers_mode = sudo_strtomode_v1(p, &mut errstr) as mode_t;
                    if !errstr.is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            *cur,
                            errstr
                        );
                        // goto bad;
                        debug_return_int!(MODE_ERROR);
                    }
                    cur = cur.offset(1);
                    continue;
                }

                if MATCHES!(*cur, b"ldap_conf=\0", 11) {
                    CHECK!(*cur, b"ldap_conf=\0", 11);
                    // path_ldap_conf = *cur + sizeof("ldap_conf=") - 1;
                    path_ldap_conf = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 11]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));
                    cur = cur.offset(1);
                    continue;
                }

                if MATCHES!(*cur, b"ldap_secret=\0", 13) {
                    CHECK!(*cur, b"ldap_secret=\0", 13);
                    path_ldap_secret = (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize,
                        )
                        .offset(-(1 as libc::c_int as isize));
                    cur = cur.offset(1);
                    continue;
                }
                cur = cur.offset(1);
            }
        }

        user_closefrom!() = -(1 as libc::c_int);
        cur = (*info).settings;

        loop {
            if (*cur).is_null() {
                break;
            }
            if MATCHES!(*cur, b"closefrom=\0", 11) {
                *__errno_location() = 0;
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 11]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                user_closefrom!() = sudo_strtonum(p, 4, INT_MAX!(), &mut errstr) as libc::c_int;

                if user_closefrom!() == 0 {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"runas_user=\0", 12) {
                CHECK!(*cur, b"runas_user=\0", 12);
                *runas_user = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 12]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                SET!(sudo_user.flags, RUNAS_USER_SPECIFIED);
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"runas_group=\0", 13) {
                CHECK!(*cur, b"runas_group=\0", 13);
                *runas_group = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                SET!(sudo_user.flags, RUNAS_GROUP_SPECIFIED);
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"prompt=\0", 8) {
                /* Allow epmpty prompt. */
                user_prompt!() = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 8]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                def_passprompt_override!() = 1 as libc::c_int;
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"set_home=\0", 10) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 9]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_ulong) as libc::c_int,
                    &mut flags,
                    MODE_RESET_HOME,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"preserve_environment=\0", 22) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 21]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_PRESERVE_ENV,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"run_shell=\0", 11) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 10]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_SHELL,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"login_shell=\0", 13) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 12]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_LOGIN_SHELL,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"implied_shell=\0", 15) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_IMPLIED_SHELL,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"preserve_groups=\0", 17) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_PRESERVE_GROUPS,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"ignore_ticket=\0", 15) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_IGNORE_TICKET,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"noninteractive=\0", 16) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 15]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_NONINTERACTIVE,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"utsudoedit=\0", 12) {
                if parse_bool(
                    *cur,
                    (::core::mem::size_of::<[libc::c_char; 11]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                        as libc::c_int,
                    &mut flags,
                    MODE_EDIT,
                ) == -(1 as libc::c_int)
                {
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"login_class=\0", 13) {
                CHECK!(*cur, b"login_class=\0", 13);
                login_class!() = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                def_use_loginclass!() = 1 as libc::c_int;
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"selinux_role=\0", 14) {
                CHECK!(*cur, b"selinux_role=\0", 14);
                user_role!() = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"selinux_type=\0", 14) {
                CHECK!(*cur, b"selinux_type=\0", 14);
                user_type!() = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"network_addrs=\0", 15) {
                interfaces_string = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 15]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                if !set_interfaces(interfaces_string) {
                    sudo_warn!(
                        b"unable to parse network address list\0" as *const u8
                            as *const libc::c_char,
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"max_groups=\0", 12) {
                *__errno_location() = 0;
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 12]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                sudo_user.max_groups = sudo_strtonum(p, 1, INT_MAX!(), &mut errstr) as libc::c_int;
                if sudo_user.max_groups == 0 {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"remote_host=\0", 13) {
                CHECK!(*cur, b"remote_host=\0", 13);
                remhost = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"timeout=\0", 9) {
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 9]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                user_timeout!() = parse_timeout(p);
                if user_timeout!() == -1 {
                    if *__errno_location() == ERANGE {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            p,
                            b"timeout value too large\0" as *const u8 as *const libc::c_char
                        );
                    } else {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            p,
                            b"invalid timeout value\0" as *const u8 as *const libc::c_char
                        );
                    }
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }
            if MATCHES!(*cur, b"plugin_dir=\0", 12) {
                CHECK!(*cur, b"plugin_dir=\0", 12);
                path_plugin_dir = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 12]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));
                cur = cur.offset(1);
                continue;
            }

            cur = cur.offset(1);
        }

        /* Sudo front-end should restrict mode flags for sudoedit. */
        if ISSET!(flags, MODE_EDIT) != 0 && (flags & edit_mask) != flags {
            sudo_warnx!(
                b"invalid mode flags from sudo front end: 0x%x\0" as *const u8
                    as *const libc::c_char,
                flags,
            );
            // goto bad;
            debug_return_int!(MODE_ERROR);
        }

        user_gid!() = -(1 as libc::c_int) as gid_t;
        user_sid!() = -(1 as libc::c_int);
        user_uid!() = -(1 as libc::c_int) as gid_t;
        user_umask!() = -(1 as libc::c_int) as mode_t;
        cur = (*info).user_info;
        loop {
            if (*cur).is_null() {
                break;
            }

            if MATCHES!(*cur, b"user=\0", 6) {
                CHECK!(*cur, b"user=\0", 6);
                user_name!() = strdup(
                    (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong as isize
                        )
                        .offset(-(1 as libc::c_int as isize)),
                );
                if user_name!().is_null() {
                    // goto oom;
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"uid=\0", 5) {
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                user_uid!() = sudo_strtoid_v2(p, &mut errstr);
                if !errstr.is_null() {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"gid=\0", 5) {
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                user_gid!() = sudo_strtoid_v2(p, &mut errstr);
                if !errstr.is_null() {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"groups=\0", 8) {
                CHECK!(*cur, b"groups=\0", 8);
                groups = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 8]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"cwd=\0", 5) {
                CHECK!(*cur, b"cwd=\0", 5);
                user_cwd!() = strdup(
                    (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong as isize
                        )
                        .offset(-(1 as libc::c_int as isize)),
                );
                if user_cwd!().is_null() {
                    // goto oom;
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"tty=\0", 5) {
                CHECK!(*cur, b"tty=\0", 5);
                user_ttypath!() = strdup(
                    (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong as isize
                        )
                        .offset(-(1 as libc::c_int as isize)),
                );
                if user_ttypath!().is_null() {
                    // goto oom;
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    debug_return_int!(MODE_ERROR);
                }

                user_tty!() = user_ttypath!();
                if strncmp(
                    user_tty!(),
                    _PATH_DEV!(),
                    (::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong),
                ) == 0 as libc::c_int
                {
                    user_tty!() = user_tty!().offset(
                        (::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong)
                            .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                            as isize,
                    );
                }

                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"host=\0", 6) {
                CHECK!(*cur, b"host=\0", 6);
                user_host!() = strdup(
                    (*cur)
                        .offset(
                            ::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong as isize
                        )
                        .offset(-(1 as libc::c_int as isize)),
                );
                if user_host!().is_null() {
                    // goto oom;
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    debug_return_int!(MODE_ERROR);
                }

                p = strchr(user_host!(), '.' as i32);
                if !p.is_null() {
                    user_shost!() = strndup(
                        user_host!(),
                        p.offset_from(user_host!()) as libc::c_long as size_t,
                    );
                    if user_shost!().is_null() {
                        // goto oom;
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        debug_return_int!(MODE_ERROR);
                    }
                } else {
                    user_shost!() = user_host!();
                }

                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"lines=\0", 7) {
                *__errno_location() = 0;

                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 7]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                sudo_user.lines = sudo_strtonum(p, 1, INT_MAX!(), &mut errstr) as libc::c_int;
                if sudo_user.lines == 0 {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"cols=\0", 6) {
                *__errno_location() = 0;
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                sudo_user.cols = sudo_strtonum(p, 1, INT_MAX!(), &mut errstr) as libc::c_int;
                if sudo_user.cols == 0 {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"sid=\0", 5) {
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                user_sid!() = sudo_strtoid_v2(p, &mut errstr) as pid_t;
                if !errstr.is_null() {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            if MATCHES!(*cur, b"umask=\0", 7) {
                p = (*cur)
                    .offset(::core::mem::size_of::<[libc::c_char; 7]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                sudo_user.umask = sudo_strtomode_v1(p, &mut errstr) as mode_t;
                if !errstr.is_null() {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        *cur,
                        errstr
                    );
                    // goto bad;
                    debug_return_int!(MODE_ERROR);
                }
                cur = cur.offset(1);
                continue;
            }

            cur = cur.offset(1);
        }

        /* User name, user-ID, group-ID and host name must be specified. */
        if user_name!().is_null() {
            sudo_warnx!(
                b"user name not set by sudo front-end\0" as *const u8 as *const libc::c_char,
            );
            // goto bad;
            debug_return_int!(MODE_ERROR);
        }

        if user_uid!() == -(1 as libc::c_int) as uid_t {
            sudo_warnx!(b"user-ID not set by sudo front-end\0" as *const u8 as *const libc::c_char,);
            // goto bad;
            debug_return_int!(MODE_ERROR);
        }

        if user_gid!() == -(1 as libc::c_int) as gid_t {
            sudo_warnx!(
                b"group-ID not set by sudo front-end\0" as *const u8 as *const libc::c_char,
            );
            // goto bad;
            debug_return_int!(MODE_ERROR);
        }

        if user_host!().is_null() {
            sudo_warnx!(
                b"host name not set by sudo front-end\0" as *const u8 as *const libc::c_char,
            );
            // goto bad;
            debug_return_int!(MODE_ERROR);
        }

        // if ((user_runhost = strdup(remhost ? remhost : user_host)) == NULL)
        user_runhost!() = strdup(if !remhost.is_null() {
            remhost
        } else {
            user_host!()
        });
        if user_runhost!().is_null() {
            // goto oom;
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_int!(MODE_ERROR);
        }

        p = strchr(user_runhost!(), '.' as i32);
        if !p.is_null() {
            user_srunhost!() = strndup(
                user_runhost!(),
                p.offset_from(user_runhost!()) as libc::c_long as size_t,
            );
            if user_srunhost!().is_null() {
                // goto oom;
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_int!(MODE_ERROR);
            }
        } else {
            user_srunhost!() = user_runhost!();
        }

        if user_cwd!().is_null() {
            user_cwd!() = strdup(b"unknown\0" as *const u8 as *const libc::c_char);
            if user_cwd!().is_null() {
                // goto oom;
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_int!(MODE_ERROR);
            }
        }

        if user_tty!().is_null() {
            user_tty!() = strdup(b"unknown\0" as *const u8 as *const libc::c_char);
            if user_tty!().is_null() {
                // goto oom;
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                debug_return_int!(MODE_ERROR);
            }
            /* user_ttypath remains NULL */
        }

        if !groups.is_null() {
            /* sudo_parse_gids() will print a warning on error. */
            user_ngids!() = sudo_parse_gids_v1(groups, &user_gid!(), &mut user_gids!());
            if user_ngids!() == -(1 as libc::c_int) {
                // goto bad;
                debug_return_int!(MODE_ERROR);
            }
        }
        /* umask is only set in user_info[] for API 1.10 and above. */
        if user_umask!() == -(1 as libc::c_int) as mode_t {
            user_umask!() = umask(0 as libc::c_int as __mode_t);
            umask(user_umask!());
        }

        /* Always reset the environment for a login shell. */
        // if flags & 0x40000 as libc::c_int != 0
        if ISSET!(flags, MODE_LOGIN_SHELL) != 0 {
            def_env_reset!() = 1 as libc::c_int;
        }

        /* Some systems support fexecve() which we use for digest matches. */
        cmnd_fd!() = -(1 as libc::c_int);

        /* Dump settings and user info (XXX - plugin args) */
        cur = (*info).settings;
        while !(*cur).is_null() {
            sudo_debug_printf!(
                SUDO_DEBUG_INFO,
                b"settings: %s\0" as *const u8 as *const libc::c_char,
                *cur
            );
            cur = cur.offset(1);
        }
        cur = (*info).user_info;
        while !(*cur).is_null() {
            sudo_debug_printf!(
                SUDO_DEBUG_INFO,
                b"user_info: %s\0" as *const u8 as *const libc::c_char,
                *cur
            );
            cur = cur.offset(1);
        }

        debug_return_int!(flags);
    } //unsafe

    //调用不到下面代码
    // oom:
    // sudo_warnx!(
    //     b"%s: %s\0" as *const u8 as *const libc::c_char,
    //     get_function_name!(),
    //     b"unable to allocate memory\0" as *const u8 as *const libc::c_char,
    // );

    // bad:
    // debug_return_int!(MODE_ERROR);
}

/*
 * Setup the execution environment.
 * Builds up the command_info list and sets argv and envp.
 * Consumes iolog_path if not NULL.
 * Returns 1 on success and -1 on error.
 */
#[no_mangle]
pub fn sudoers_policy_exec_setup(
    mut argv: *mut *mut libc::c_char,
    mut envp: *mut *mut libc::c_char,
    mut cmnd_umask: mode_t,
    mut iolog_path: *mut libc::c_char,
    mut v: *mut libc::c_void,
) -> libc::c_int {
    let mut current_block: u64 = 0;
    let mut exec_args: *mut sudoers_exec_args = v as *mut sudoers_exec_args;
    let mut command_info: *mut *mut libc::c_char = std::ptr::null_mut::<*mut libc::c_char>();
    let mut info_len: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        'oom: loop {
            /* Increase the length of command_info as needed, it is *not* checked. */
            command_info = calloc(
                48 as libc::c_int as libc::c_ulong,
                ::core::mem::size_of::<*mut libc::c_char>() as libc::c_ulong,
            ) as *mut *mut libc::c_char;

            if command_info.is_null() {
                break 'oom;
            }

            *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                b"command\0" as *const u8 as *const libc::c_char,
                safe_cmnd!(),
            );

            let fresh1 = info_len;
            info_len += 1;
            if (*command_info.offset(fresh1 as isize)).is_null() {
                break 'oom;
            }

            if def_log_input!() != 0 || def_log_output!() != 0 {
                if !iolog_path.is_null() {
                    *command_info.offset(info_len as isize) = iolog_path; /* now owned */
                    info_len += 1;
                }

                if def_log_input!() != 0 {
                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_stdin=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;

                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_ttyin=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }

                if def_log_output!() != 0 {
                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_stdout=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;

                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_stderr=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;

                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_ttyout=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }

                if def_compress_io!() != 0 {
                    *command_info.offset(info_len as isize) =
                        strdup(b"iolog_compress=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }

                if def_maxseq!() != 0 {
                    if asprintf(
                        &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                        b"maxseq=%u\0" as *const u8 as *const libc::c_char,
                        def_maxseq!(),
                    ) == -1
                    {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }
            }

            if ISSET!(sudo_mode, MODE_EDIT) != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"utsudoedit=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;

                if def_sudoedit_checkdir!() == 0 {
                    *command_info.offset(info_len as isize) =
                        strdup(b"utsudoedit_checkdir=false\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }
                if def_sudoedit_follow!() != 0 {
                    *command_info.offset(info_len as isize) =
                        strdup(b"utsudoedit_follow=true\0" as *const u8 as *const libc::c_char);
                    if command_info.offset(info_len as isize).is_null() {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }
            }

            if ISSET!(sudo_mode, MODE_LOGIN_SHELL) != 0 {
                /* Set cwd to run user's homedir. */
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"cwd\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_dir,
                );

                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_stay_setuid!() != 0 {
                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_uid=%u\0" as *const u8 as *const libc::c_char,
                    user_uid!(),
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;

                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_gid=%u\0" as *const u8 as *const libc::c_char,
                    user_gid!(),
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;

                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_euid=%u\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_uid,
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;

                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_egid=%u\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_gid,
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            } else {
                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_uid=%u\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_uid,
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;

                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"runas_gid=%u\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_gid,
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_preserve_groups!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"preserve_groups=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            } else {
                let mut i: libc::c_int = 0;
                let mut len: libc::c_int = 0;
                let mut egid: gid_t = 0;
                let mut glsize: size_t = 0;
                let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
                let mut gid_list: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
                let mut gidlist: *mut gid_list = std::ptr::null_mut::<gid_list>();

                /* Only use results from a group db query, not the front end. */
                gidlist = sudo_get_gidlist(runas_pw!(), 0x1 as libc::c_int as libc::c_uint);

                /* We reserve an extra spot in the list for the effective gid. */
                glsize = (::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong)
                    .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                    .wrapping_add((((*gidlist).ngids + 1) * (MAX_UID_T_LEN + 1)) as libc::c_ulong);
                gid_list = malloc(glsize) as *mut libc::c_char;
                if gid_list.is_null() {
                    break 'oom;
                }
                memcpy(
                    gid_list as *mut libc::c_void,
                    b"runas_groups=\0" as *const u8 as *const libc::c_char as *const libc::c_void,
                    (::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong)
                        .wrapping_sub(1 as libc::c_int as libc::c_ulong),
                );

                cp = gid_list
                    .offset(::core::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong as isize)
                    .offset(-(1 as libc::c_int as isize));

                /* On BSD systems the effective gid is the first group in the list. */
                egid = if !runas_gr!().is_null() {
                    (*runas_gr!()).gr_gid
                } else {
                    (*runas_pw!()).pw_gid
                };
                len = snprintf(
                    cp,
                    glsize.wrapping_sub(cp.offset_from(gid_list) as libc::c_long as libc::c_ulong),
                    b"%u\0" as *const u8 as *const libc::c_char,
                    egid,
                );

                if len < 0 as libc::c_int
                    || len as size_t
                        >= glsize
                            .wrapping_sub(cp.offset_from(gid_list) as libc::c_long as libc::c_ulong)
                {
                    sudo_warnx!(
                        b"internal error, %s overflow\0" as *const u8 as *const libc::c_char,
                        get_function_name!()
                    );
                    free(gid_list as *mut libc::c_void);
                    // goto bad;
                    loop {
                        if info_len == 0 {
                            break;
                        }
                        info_len -= 1;
                        free(*command_info.offset(info_len as isize) as *mut libc::c_void);
                    }
                    free(command_info as *mut libc::c_void);
                    debug_return_int!(-1);
                }

                cp = cp.offset(len as isize);

                loop {
                    if i >= (*gidlist).ngids {
                        break;
                    }
                    if *((*gidlist).gids).offset(i as isize) != egid {
                        len = snprintf(
                            cp,
                            glsize.wrapping_sub(
                                cp.offset_from(gid_list) as libc::c_long as libc::c_ulong
                            ),
                            b",%u\0" as *const u8 as *const libc::c_char,
                            *((*gidlist).gids).offset(i as isize),
                        );
                        if len < 0 as libc::c_int
                            || len as size_t
                                >= glsize.wrapping_sub(
                                    cp.offset_from(gid_list) as libc::c_long as libc::c_ulong
                                )
                        {
                            sudo_warnx!(
                                b"internal error, %s overflow\0" as *const u8
                                    as *const libc::c_char,
                                get_function_name!(),
                            );
                            free(gid_list as *mut libc::c_void);
                            // goto bad;
                            loop {
                                if info_len == 0 {
                                    break;
                                }
                                info_len -= 1;
                                free(*command_info.offset(info_len as isize) as *mut libc::c_void);
                            }
                            free(command_info as *mut libc::c_void);
                            debug_return_int!(-1);
                        }
                        cp = cp.offset(len as isize);
                    }
                    i += 1;
                }

                *command_info.offset(info_len as isize) = gid_list;
                info_len += 1;

                sudo_gidlist_delref(gidlist);
            }

            if def_closefrom!() > 0 {
                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"closefrom=%d\0" as *const u8 as *const libc::c_char,
                    def_closefrom!(),
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_ignore_iolog_errors!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"ignore_iolog_errors=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_noexec!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"noexec=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if def_exec_background!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"exec_background=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if def_set_utmp!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"set_utmp=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if def_use_pty!() != 0 {
                *command_info.offset(info_len as isize) =
                    strdup(b"use_pty=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_utmp_runas!() != 0 {
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"utmp_user\0" as *const u8 as *const libc::c_char,
                    (*runas_pw!()).pw_name,
                );
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_iolog_mode!() != (S_IRUSR!() | S_IWUSR!()) {
                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"iolog_mode=0%o\0" as *const u8 as *const libc::c_char,
                    def_iolog_mode!(),
                ) == -(1 as libc::c_int)
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if !def_iolog_user!().is_null() {
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"iolog_user\0" as *const u8 as *const libc::c_char,
                    def_iolog_user!(),
                );
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if !def_iolog_group!().is_null() {
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"iolog_group\0" as *const u8 as *const libc::c_char,
                    def_iolog_group!(),
                );
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if def_command_timeout!() > 0 || user_timeout!() > 0 {
                let mut timeout: libc::c_int = user_timeout!();
                if timeout == 0 || def_command_timeout!() < timeout {
                    timeout = def_command_timeout!();
                }

                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"timeout=%u\0" as *const u8 as *const libc::c_char,
                    timeout,
                ) == -1
                {
                    // goto oom;
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if cmnd_umask != ACCESSPERMS!() as libc::c_uint {
                if asprintf(
                    &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                    b"umask=0%o\0" as *const u8 as *const libc::c_char,
                    cmnd_umask,
                ) == -1
                {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            if force_umask {
                *command_info.offset(info_len as isize) =
                    strdup(b"umask_override=true\0" as *const u8 as *const libc::c_char);
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if cmnd_fd!() != -1 {
                if sudo_version < SUDO_API_MKVERSION!(1, 9) {
                    /* execfd only supported by plugin API 1.9 and higher */
                    close(cmnd_fd!());
                    cmnd_fd!() = -1;
                } else {
                    if asprintf(
                        &mut *command_info.offset(info_len as isize) as *mut *mut libc::c_char,
                        b"execfd=%d\0" as *const u8 as *const libc::c_char,
                        cmnd_fd!(),
                    ) == -1
                    {
                        info_len += 1;
                        break 'oom;
                    }
                    info_len += 1;
                }
            }

            if !user_role!().is_null() {
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"selinux_role\0" as *const u8 as *const libc::c_char,
                    user_role!(),
                );
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }
            if !user_type!().is_null() {
                *command_info.offset(info_len as isize) = sudo_new_key_val_v1(
                    b"selinux_type\0" as *const u8 as *const libc::c_char,
                    user_type!(),
                );
                if command_info.offset(info_len as isize).is_null() {
                    info_len += 1;
                    break 'oom;
                }
                info_len += 1;
            }

            /* Free on exit; they are not available in the close function. */
            sudoers_gc_add(GC_VECTOR, argv as *mut libc::c_void);
            sudoers_gc_add(GC_VECTOR, envp as *mut libc::c_void);
            sudoers_gc_add(GC_VECTOR, command_info as *mut libc::c_void);

            /* Fill in exec environment info. */
            *(*exec_args).argv = argv;
            *(*exec_args).envp = envp;
            *(*exec_args).info = command_info;

            debug_return_int!(1);

            // break 'oom;
        } // 'oom loop

        //下面代码应该执行不到
        // oom:
        sudo_warnx!(
            b"%s: %s\0" as *const u8 as *const libc::c_char,
            get_function_name!(),
            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
        );

        // bad:
        loop {
            if info_len == 0 {
                break;
            }
            info_len -= 1;
            free(*command_info.offset(info_len as isize) as *mut libc::c_void);
        }
        free(command_info as *mut libc::c_void);
        debug_return_int!(-1);
    } //unsafe
}

unsafe extern "C" fn sudoers_policy_open(
    mut version: libc::c_uint,
    mut conversation: sudo_conv_t,
    mut plugin_printf: sudo_printf_t,
    mut settings: *const *mut libc::c_char,
    mut user_info: *const *mut libc::c_char,
    mut envp: *const *mut libc::c_char,
    mut args: *const *mut libc::c_char,
) -> libc::c_int {
    let mut debug_files: sudo_conf_debug_file_list = sudo_conf_debug_file_list {
        tqh_first: std::ptr::null_mut::<sudo_debug_file>(),
        tqh_last: std::ptr::null_mut::<*mut sudo_debug_file>(),
    };
    debug_files = {
        sudo_conf_debug_file_list {
            tqh_first: std::ptr::null_mut::<sudo_debug_file>(),
            tqh_last: &mut debug_files.tqh_first,
        }
        //init
    };
    let mut info: sudoers_policy_open_info = sudoers_policy_open_info {
        settings: std::ptr::null::<*mut libc::c_char>(),
        user_info: std::ptr::null::<*mut libc::c_char>(),
        plugin_args: std::ptr::null::<*mut libc::c_char>(),
    };
    let mut cp: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut plugin_path: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut cur: *const *mut libc::c_char = std::ptr::null::<*mut libc::c_char>();
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    sudo_version = version;
    sudo_conv = conversation;
    sudo_printf = plugin_printf;

    /* Plugin args are only specified for API version 1.2 and higher. */
    if sudo_version < SUDO_API_MKVERSION!(1, 2) {
        args = std::ptr::null::<*mut libc::c_char>();
    }

    /* Initialize the debug subsystem.  */
    cur = settings;
    loop {
        cp = *cur;
        if cp.is_null() {
            break;
        }
        if strncmp(
            cp,
            b"debug_flags=\0" as *const u8 as *const libc::c_char,
            (::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong)
                .wrapping_sub(1 as libc::c_int as libc::c_ulong),
        ) == 0 as libc::c_int
        {
            cp = cp.offset(
                (::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong)
                    .wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize,
            );
            if !sudoers_debug_parse_flags(&mut debug_files, cp) {
                debug_return_int!(-1);
            }
            cur = cur.offset(1);
            continue;
        }

        if strncmp(
            cp,
            b"plugin_path=\0" as *const u8 as *const libc::c_char,
            (::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong)
                .wrapping_sub(1 as libc::c_int as libc::c_ulong),
        ) == 0 as libc::c_int
        {
            plugin_path = cp
                .offset(::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong as isize)
                .offset(-(1 as libc::c_int as isize));

            cur = cur.offset(1);
            continue;
        }
        cur = cur.offset(1);
    }

    if !sudoers_debug_register(plugin_path, &mut debug_files) {
        debug_return_int!(-1);
    }

    /* Call the sudoers init function. */
    info.settings = settings;
    info.user_info = user_info;
    info.plugin_args = args;

    let ret = sudoers_policy_init(
        &mut info as *mut sudoers_policy_open_info as *mut libc::c_void,
        envp,
    );

    debug_return_int!(ret);
}
unsafe extern "C" fn sudoers_policy_close(
    mut exit_status: libc::c_int,
    mut error_code: libc::c_int,
) {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* We do not currently log the exit status. */
    if error_code != 0 {
        *__errno_location() = error_code;
        sudo_warn!(
            b"unable to execute %s\0" as *const u8 as *const libc::c_char,
            safe_cmnd!()
        );
    }

    /* Close the session we opened in sudoers_policy_init_session(). */
    if ISSET!(sudo_mode, MODE_RUN | MODE_EDIT) != 0 {
        sudo_auth_end_session(runas_pw!());
    }

    /* Deregister the callback for sudo_fatal()/sudo_fatalx(). */
    sudo_fatal_callback_deregister_v1(Some(sudoers_cleanup as unsafe extern "C" fn() -> ()));

    /* Free remaining references to password and group entries. */
    /* XXX - move cleanup to function in sudoers.c */
    sudo_pw_delref(sudo_user.pw);
    sudo_user.pw = std::ptr::null_mut::<passwd>();
    sudo_pw_delref(runas_pw!());

    runas_pw!() = std::ptr::null_mut::<passwd>();
    if !runas_gr!().is_null() {
        sudo_gr_delref(runas_gr!());
        runas_gr!() = std::ptr::null_mut::<group>();
    }
    if !user_gid_list!().is_null() {
        sudo_gidlist_delref(user_gid_list!());
        user_gid_list!() = std::ptr::null_mut::<gid_list>();
    }
    free(user_gids!() as *mut libc::c_void);
    user_gids!() = std::ptr::null_mut::<gid_t>();
    sudoers_debug_deregister();

    //return;
}

/*
 * The init_session function is called before executing the command
 * and before uid/gid changes occur.
 * Returns 1 on success, 0 on failure and -1 on error.
 */
unsafe extern "C" fn sudoers_policy_init_session(
    mut pwd: *mut passwd,
    mut user_env: *mut *mut *mut libc::c_char,
) -> libc::c_int {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    /* user_env is only specified for API version 1.2 and higher. */
    if sudo_version < SUDO_API_MKVERSION!(1, 2) {
        user_env = std::ptr::null_mut::<*mut *mut libc::c_char>();
    }

    debug_return_int!(sudo_auth_begin_session(pwd, user_env));
}
unsafe extern "C" fn sudoers_policy_check(
    mut argc: libc::c_int,
    mut argv: *const *mut libc::c_char,
    mut env_add: *mut *mut libc::c_char,
    mut command_infop: *mut *mut *mut libc::c_char,
    mut argv_out: *mut *mut *mut libc::c_char,
    mut user_env_out: *mut *mut *mut libc::c_char,
) -> libc::c_int {
    let mut exec_args: sudoers_exec_args = sudoers_exec_args {
        argv: std::ptr::null_mut::<*mut *mut libc::c_char>(),
        envp: std::ptr::null_mut::<*mut *mut libc::c_char>(),
        info: std::ptr::null_mut::<*mut *mut libc::c_char>(),
    };
    let mut ret: libc::c_int = 0;
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    if ISSET!(sudo_mode, MODE_EDIT) == 0 {
        SET!(sudo_mode, MODE_RUN);
    }
    exec_args.argv = argv_out;
    exec_args.envp = user_env_out;
    exec_args.info = command_infop;

    ret = sudoers_policy_main(
        argc,
        argv,
        0 as libc::c_int,
        env_add,
        0 as libc::c_int != 0,
        &mut exec_args as *mut sudoers_exec_args as *mut libc::c_void,
    );

    if ret == 1 && sudo_version >= SUDO_API_MKVERSION!(1, 3) as libc::c_uint {
        /* Unset close function if we don't need it to avoid extra process. */
        if def_log_input!() == 0
            && def_log_output!() == 0
            && def_use_pty!() == 0
            && !sudo_auth_needs_end_session()
        {
            sudoers_policy.close = None;
        }
    }
    debug_return_int!(ret);
}
unsafe extern "C" fn sudoers_policy_validate() -> libc::c_int {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    user_cmnd!() = b"validate\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
    SET!(sudo_mode, MODE_VALIDATE);

    let mut fin_ret: libc::c_int = sudoers_policy_main(
        0 as libc::c_int,
        std::ptr::null::<*mut libc::c_char>(),
        I_VERIFYPW as libc::c_int,
        std::ptr::null_mut::<*mut libc::c_char>(),
        0 as libc::c_int != 0,
        std::ptr::null_mut::<libc::c_void>(),
    );

    debug_return_int!(fin_ret);
}
unsafe extern "C" fn sudoers_policy_invalidate(mut remove: libc::c_int) {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    user_cmnd!() = b"kill\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
    /* XXX - plugin API should support a return value for fatal errors. */
    timestamp_remove(remove != 0);
    sudoers_cleanup();

    debug_return!();
}
unsafe extern "C" fn sudoers_policy_list(
    mut argc: libc::c_int,
    mut argv: *const *mut libc::c_char,
    mut verbose: libc::c_int,
    mut list_user: *const libc::c_char,
) -> libc::c_int {
    let mut ret: libc::c_int = 0;
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    user_cmnd!() = b"list\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
    if argc != 0 {
        // sudo_mode |= 0x100 as libc::c_int;
        SET!(sudo_mode, MODE_CHECK);
    } else {
        // sudo_mode |= 0x80 as libc::c_int;
        SET!(sudo_mode, MODE_LIST);
    }
    if !list_user.is_null() {
        list_pw = sudo_getpwnam(list_user);
        if list_pw.is_null() {
            sudo_warnx!(
                b"unknown user: %s\0" as *const u8 as *const libc::c_char,
                list_user
            );
            debug_return_int!(-1);
        }
    }
    ret = sudoers_policy_main(
        argc,
        argv,
        I_LISTPW as libc::c_int,
        std::ptr::null_mut::<*mut libc::c_char>(),
        verbose != 0,
        std::ptr::null_mut::<libc::c_void>(),
    );
    if !list_user.is_null() {
        sudo_pw_delref(list_pw);
        list_pw = std::ptr::null_mut::<passwd>();
    }

    debug_return_int!(ret);
}

unsafe extern "C" fn sudoers_policy_version(mut verbose: libc::c_int) -> libc::c_int {
    debug_decl!(SUDOERS_DEBUG_PLUGIN!());

    sudo_printf.expect("non-null function pointer")(
        SUDO_CONV_INFO_MSG,
        b"Sudoers policy plugin version %s\n\0" as *const u8 as *const libc::c_char,
        PACKAGE_VERSION!(),
    );

    sudo_printf.expect("non-null function pointer")(
        SUDO_CONV_INFO_MSG,
        b"Sudoers file grammar version %d\n\0" as *const u8 as *const libc::c_char,
        SUDOERS_GRAMMAR_VERSION,
    );

    if verbose != 0 {
        sudo_printf.expect("non-null function pointer")(
            SUDO_CONV_INFO_MSG,
            b"\nSudoers path: %s\n\0" as *const u8 as *const libc::c_char,
            sudoers_file,
        );

        sudo_printf.expect("non-null function pointer")(
            SUDO_CONV_INFO_MSG,
            b"nsswitch path: %s\n\0" as *const u8 as *const libc::c_char,
            _PATH_NSSWITCH_CONF!(),
        );

        sudo_printf.expect("non-null function pointer")(
            SUDO_CONV_INFO_MSG,
            b"ldap.conf path: %s\n\0" as *const u8 as *const libc::c_char,
            path_ldap_conf,
        );

        sudo_printf.expect("non-null function pointer")(
            SUDO_CONV_INFO_MSG,
            b"ldap.secret path: %s\n\0" as *const u8 as *const libc::c_char,
            path_ldap_secret,
        );

        dump_auth_methods();
        dump_defaults();
        sudo_printf.expect("non-null function pointer")(
            0x4 as libc::c_int,
            b"\n\0" as *const u8 as *const libc::c_char,
        );

        sudo_printf.expect("non-null function pointer")(
            SUDO_CONV_INFO_MSG,
            b"\n\0" as *const u8 as *const libc::c_char,
        );

        if !interfaces_string.is_null() {
            dump_interfaces(interfaces_string);
            sudo_printf.expect("non-null function pointer")(
                SUDO_CONV_INFO_MSG,
                b"\n\0" as *const u8 as *const libc::c_char,
            );
        }
    }

    debug_return_int!(1 as libc::c_int);
}

static mut sudoers_hooks: [sudo_hook; 5] = unsafe {
    [
        {
            sudo_hook {
                hook_version: SUDO_HOOK_VERSION!(),
                hook_type: SUDO_HOOK_SETENV,
                hook_fn: ::core::mem::transmute::<
                    Option<
                        unsafe extern "C" fn(
                            *const libc::c_char,
                            *const libc::c_char,
                            libc::c_int,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                    >,
                    sudo_hook_fn_t,
                >(Some(
                    sudoers_hook_setenv
                        as unsafe extern "C" fn(
                            *const libc::c_char,
                            *const libc::c_char,
                            libc::c_int,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                )),
                closure: 0 as *const libc::c_void as *mut libc::c_void,
            }
            //init
        },
        {
            sudo_hook {
                hook_version: SUDO_HOOK_VERSION!(),
                hook_type: SUDO_HOOK_UNSETENV,
                hook_fn: ::core::mem::transmute::<
                    Option<
                        unsafe extern "C" fn(*const libc::c_char, *mut libc::c_void) -> libc::c_int,
                    >,
                    sudo_hook_fn_t,
                >(Some(
                    sudoers_hook_unsetenv
                        as unsafe extern "C" fn(
                            *const libc::c_char,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                )),
                closure: 0 as *const libc::c_void as *mut libc::c_void,
            }
            //init
        },
        {
            sudo_hook {
                hook_version: SUDO_HOOK_VERSION!(),
                hook_type: SUDO_HOOK_GETENV,
                hook_fn: ::core::mem::transmute::<
                    Option<
                        unsafe extern "C" fn(
                            *const libc::c_char,
                            *mut *mut libc::c_char,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                    >,
                    sudo_hook_fn_t,
                >(Some(
                    sudoers_hook_getenv
                        as unsafe extern "C" fn(
                            *const libc::c_char,
                            *mut *mut libc::c_char,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                )),
                closure: 0 as *const libc::c_void as *mut libc::c_void,
            }
            //init
        },
        {
            sudo_hook {
                hook_version: SUDO_HOOK_VERSION!(),
                hook_type: SUDO_HOOK_PUTENV,
                hook_fn: ::core::mem::transmute::<
                    Option<
                        unsafe extern "C" fn(*mut libc::c_char, *mut libc::c_void) -> libc::c_int,
                    >,
                    sudo_hook_fn_t,
                >(Some(
                    sudoers_hook_putenv
                        as unsafe extern "C" fn(
                            *mut libc::c_char,
                            *mut libc::c_void,
                        ) -> libc::c_int,
                )),
                closure: 0 as *const libc::c_void as *mut libc::c_void,
            }
            //init
        },
        {
            sudo_hook {
                hook_version: 0 as libc::c_int as libc::c_uint,
                hook_type: 0 as libc::c_int as libc::c_uint,
                hook_fn: None,
                closure: 0 as *const libc::c_void as *mut libc::c_void,
            }
            //init
        },
    ]
};

/*
 * Register environment function hooks.
 * Note that we have not registered sudoers with the debug subsystem yet.
 */
unsafe extern "C" fn sudoers_policy_register_hooks(
    mut version: libc::c_int,
    mut register_hook: Option<unsafe extern "C" fn(*mut sudo_hook) -> libc::c_int>,
) {
    let mut hook: *mut sudo_hook = std::ptr::null_mut::<sudo_hook>();
    hook = sudoers_hooks.as_mut_ptr();
    while ((*hook).hook_fn).is_some() {
        if register_hook.expect("non-null function pointer")(hook) != 0 as libc::c_int {
            sudo_warn_nodebug_v1(
                sudo_warn_gettext_v1(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"unable to register hook of type %d (version %d.%d)\0" as *const u8
                        as *const libc::c_char,
                ),
                (*hook).hook_type,
                SUDO_API_VERSION_GET_MAJOR!((*hook).hook_version),
                SUDO_API_VERSION_GET_MINOR!((*hook).hook_version),
            );
        }
        hook = hook.offset(1);
    }
}

#[no_mangle]
pub static mut sudoers_policy: policy_plugin = unsafe {
    {
        policy_plugin {
            type_0: 1 as libc::c_int as libc::c_uint,
            version: ((1 as libc::c_int) << 16 as libc::c_int | 14 as libc::c_int) as libc::c_uint,
            open: Some(
                sudoers_policy_open
                    as unsafe extern "C" fn(
                        libc::c_uint,
                        sudo_conv_t,
                        sudo_printf_t,
                        *const *mut libc::c_char,
                        *const *mut libc::c_char,
                        *const *mut libc::c_char,
                        *const *mut libc::c_char,
                    ) -> libc::c_int,
            ),
            close: Some(
                sudoers_policy_close as unsafe extern "C" fn(libc::c_int, libc::c_int) -> (),
            ),
            show_version: Some(
                sudoers_policy_version as unsafe extern "C" fn(libc::c_int) -> libc::c_int,
            ),
            check_policy: Some(
                sudoers_policy_check
                    as unsafe extern "C" fn(
                        libc::c_int,
                        *const *mut libc::c_char,
                        *mut *mut libc::c_char,
                        *mut *mut *mut libc::c_char,
                        *mut *mut *mut libc::c_char,
                        *mut *mut *mut libc::c_char,
                    ) -> libc::c_int,
            ),
            list: Some(
                sudoers_policy_list
                    as unsafe extern "C" fn(
                        libc::c_int,
                        *const *mut libc::c_char,
                        libc::c_int,
                        *const libc::c_char,
                    ) -> libc::c_int,
            ),
            validate: Some(sudoers_policy_validate as unsafe extern "C" fn() -> libc::c_int),
            invalidate: Some(sudoers_policy_invalidate as unsafe extern "C" fn(libc::c_int) -> ()),
            init_session: Some(
                sudoers_policy_init_session
                    as unsafe extern "C" fn(
                        *mut passwd,
                        *mut *mut *mut libc::c_char,
                    ) -> libc::c_int,
            ),
            register_hooks: Some(
                sudoers_policy_register_hooks
                    as unsafe extern "C" fn(
                        libc::c_int,
                        Option<unsafe extern "C" fn(*mut sudo_hook) -> libc::c_int>,
                    ) -> (),
            ),
            deregister_hooks: None,
        }
        //init
    }
};
